using System;
using AudioComponent;
using EntitiesAndGameState;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Services;
using WAG.Logic.SampleLevel;

namespace WAG.Menu
{

    using System.Threading;
    using Game = Microsoft.Xna.Framework.Game;

  public static class StateManager
  {

    public static void SelectMenu(Game game)
    {
      try
      {
        CleanupComponents(game);
        game.Components.Add(new Background(game, BackgroundType.DefaulsBackground));
        game.Components.Add(new MainMenu(game));
      }
      catch (Exception e)
      {
        StateManager.SelectIntroScreen(game);
      }
    }


    public static void SelectLanguagesScreen(Game game)
    {
      CleanupComponents(game);
      game.Components.Add(new LanguageSelection(game, new Language[] { 
            new Language { Flag = game.Content.Load<Texture2D>("Languages/uk-us_flag"), Tag = "en"},
            new Language { Flag = game.Content.Load<Texture2D>("Languages/es_flag"), Tag = "es"},
            new Language {Flag = game.Content.Load<Texture2D>("Languages/it_flag"), Tag = "it"},
            new Language { Flag = game.Content.Load<Texture2D>("Languages/de_flag"), Tag = "de"},
            new Language { Flag = game.Content.Load<Texture2D>("Languages/fr_flag"), Tag = "fr"} }));
    }

    public static void SelectIntroScreen(Game game)
    {
      CleanupComponents(game);

      var logo_screen = new LogoScreen(game, "Menu/vst_logo");
      game.Components.Add(logo_screen);
    }




    #region Level Start no Multi-Thread
    /*
        public static void StartCampaignLevel(Game game, GarbageType selected_ship)
        {
            CleanupComponents(game);

            var loading_screen = new LoadingScreen(game);

            loading_screen.OnLoadEnd += () =>
            {
                loading_screen.start_fadeoff_transition = true;
            };

            loading_screen.OnLoadBegin += () =>
            {
                var current_state = Leaderboard.GetCampaignState().CampaignState;
                var li = CampaignLevel.GetCampaignLevel(current_state.LevelPlayed);

                var score = current_state.Score;

                var sample_level = new CampaignMode(game,
                      new BaseLevelStats()
                      {
                          TotalScore = score,
                          Credits = current_state.Credits
                      }, li, selected_ship, current_state.Lives);
                sample_level.OnLevelLost += (match_data) =>
                {
                    StateManager.CleanupComponents(game);
                    game.Components.Add(new DefeatScreen(game, GameMode.Campaign, match_data));
                };
                sample_level.OnLevelWon += (victory_data) =>
                {
                    StateManager.CleanupComponents(game);
                    game.Components.Add(new VictoryScreen(game, GameMode.Campaign, victory_data));
                };

                var audio_manager = new AudioManager(game);
                var scene_renderer = new OverlaysLayer(game);
                var input_manager = new InputManager(game);
                game.Components.Add(sample_level);
                game.Components.Add(scene_renderer);
                game.Components.Add(audio_manager);
                game.Components.Add(new UIRenderer(game));
                game.Components.Add(input_manager);
                game.Components.Add(new Background(game, BackgroundType.Atlantis));
                GC.Collect();
                GC.WaitForPendingFinalizers();

                LoadingScreen.LoadProccesComplete(game);
            };

            game.Components.Add(loading_screen);
        }

        public static void SelectSkirmishLevel(Game game, int enemies_n, int difficulty, bool boss)
        {
            CleanupComponents(game);

            var ship_selection = new ShipSelectionScreen(game, GameMode.Skirmish);
            ship_selection.OnShipSelected += ship_selected =>
            {
                CleanupComponents(game);

                var loading_screen = new LoadingScreen(game);

                var num_lives = difficulty == 2 ? 0 : 3 - difficulty;
                var wave_left = difficulty * 2 + 1 + (boss ? 1 : 0);

                loading_screen.OnLoadEnd += () =>
                {
                    loading_screen.start_fadeoff_transition = true;
                };

                loading_screen.OnLoadBegin += () =>
                {
                    var sample_level = new SkirmishMode(game,
                      new BaseLevelStats()
                      {
                          TotalScore = 0,
                          Credits = 0
                      }, ship_selected, num_lives, enemies_n, wave_left, boss);
                    sample_level.OnLevelLost += (match_data) =>
                    {
                        StateManager.CleanupComponents(game);
                        game.Components.Add(new DefeatScreen(game, GameMode.Skirmish, match_data));
                    };
                    sample_level.OnLevelWon += (victory_data) =>
                    {
                        StateManager.CleanupComponents(game);
                        game.Components.Add(new VictoryScreen(game, GameMode.Skirmish, victory_data));
                    };

                    var audio_manager = new AudioManager(game);
                    var scene_renderer = new OverlaysLayer(game);
                    var input_manager = new InputManager(game);
                    game.Components.Add(sample_level);
                    game.Components.Add(scene_renderer);
                    game.Components.Add(audio_manager);
                    game.Components.Add(new UIRenderer(game));
                    game.Components.Add(input_manager);
                    game.Components.Add(new Background(game, BackgroundType.Atlantis));
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                };

                game.Components.Add(loading_screen);
            };
            game.Components.Add(new InputManager(game));
            game.Components.Add(ship_selection);
        }

        public static void SelectSurvivalLevel(Game game, GameMode game_mode)
        {
            CleanupComponents(game);

            var ship_selection = new ShipSelectionScreen(game, GameMode.Survival);
            ship_selection.OnShipSelected += ship_selected =>
            {
                CleanupComponents(game);

                var initial_lives_n = 3;

                var loading_screen = new LoadingScreen(game);

                loading_screen.OnLoadEnd += () =>
                {
                    loading_screen.start_fadeoff_transition = true;
                };

                loading_screen.OnLoadBegin += () =>
                {
                    var sample_level = new SurvivalMode(game,
                      new BaseLevelStats()
                      {
                          TotalScore = 0,
                          Credits = 0
                      }, ship_selected, initial_lives_n);
                    sample_level.OnLevelLost += (match_data) =>
                    {
                        StateManager.CleanupComponents(game);
                        game.Components.Add(new DefeatScreen(game, GameMode.Survival, match_data));
                    };
                    sample_level.OnLevelWon += (victory_data) =>
                    {
                        StateManager.CleanupComponents(game);
                        game.Components.Add(new VictoryScreen(game, GameMode.Survival, victory_data));
                    };

                    var audio_manager = new AudioManager(game);
                    var scene_renderer = new OverlaysLayer(game);
                    var input_manager = new InputManager(game);
                    game.Components.Add(sample_level);
                    game.Components.Add(scene_renderer);
                    game.Components.Add(audio_manager);
                    game.Components.Add(new UIRenderer(game));
                    game.Components.Add(input_manager);
                    game.Components.Add(new Background(game, BackgroundType.Atlantis));
                    GC.Collect();
                    GC.WaitForPendingFinalizers();

                    LoadingScreen.LoadProccesComplete(game);
                };

                game.Components.Add(loading_screen);
            };
            game.Components.Add(new InputManager(game));
            game.Components.Add(ship_selection);
        }
        */
    #endregion

    #region Level Start Multi-Thread

    //public static void StartCampaignLevel(Game game, GarbageType selected_ship)

    //public static void SelectSkirmishLevel(Game game, int enemies_n, int difficulty, bool boss)
    //{
    //    CleanupComponents(game);

    //    var ship_selection = new ShipSelectionScreen(game, GameMode.Skirmish);
    //    ship_selection.OnShipSelected += ship_selected =>
    //    {
    //        CleanupComponents(game);

    //        var loading_screen = new LoadingScreen(game, true);

    //        var num_lives = difficulty == 2 ? 0 : 3 - difficulty;
    //        var wave_left = difficulty * 2 + 1 + (boss ? 1 : 0);

    //        loading_screen.OnLoadEnd += () =>
    //        {
    //            loading_screen.start_fadeoff_transition = true;
    //        };

    //        loading_screen.OnLoadBegin += () =>
    //        {
    //            var sample_level = new SkirmishMode(game,
    //              new BaseLevelStats()
    //              {
    //                  TotalScore = 0,
    //                  Credits = 0
    //              }, ship_selected, num_lives, enemies_n, wave_left, boss);
    //            sample_level.OnLevelLost += (match_data) =>
    //            {
    //                StateManager.CleanupComponents(game);
    //                game.Components.Add(new DefeatScreen(game, GameMode.Skirmish, match_data));
    //            };
    //            sample_level.OnLevelWon += (victory_data) =>
    //            {
    //                StateManager.CleanupComponents(game);
    //                game.Components.Add(new VictoryScreen(game, GameMode.Skirmish, victory_data));
    //            };

    //            var audio_manager = new AudioManager(game);
    //            var scene_renderer = new OverlaysLayer(game);
    //            var input_manager = new InputManager(game);

    //            sample_level.Enabled = false;
    //            input_manager.Enabled = false;
    //            scene_renderer.Enabled = false;

    //            game.Components.Add(sample_level);
    //            game.Components.Add(scene_renderer);
    //            game.Components.Add(audio_manager);
    //            game.Components.Add(new UIRenderer(game, GameMode.Skirmish));
    //            game.Components.Add(input_manager);
    //            var r = new Random();
    //            game.Components.Add(new Background(game, (BackgroundType)r.Next(Background.NumberOf)));
    //            GC.Collect();
    //            GC.WaitForPendingFinalizers();
    //        };

    //        game.Components.Add(loading_screen);
    //    };

    //    game.Components.Add(ship_selection);
    //}

    public static void SelectSurvivalLevel(
                          Game game, 
                          Thread external_thread, 
                          bool resume_state,
                          GameMode game_mode
                          //FSharpFunc<Tuple<IStateProvider<BaseLevelStats>, UnfoldMonad.RenderState, Component.Time, Component.Time>, UnfoldMonad.Step<GameState, IStateProvider<BaseLevelStats>, UnfoldMonad.RenderState>> _script)
        )
    {
      CleanupComponents(game);

      if (external_thread != null)
        external_thread.Join();

      var graphics = (GraphicsDeviceManager)game.Services.GetService(typeof(GraphicsDeviceManager));

      //graphics.SupportedOrientations = DisplayOrientation.LandscapeRight;
      //graphics.PreferredBackBufferWidth = 800;
      //graphics.PreferredBackBufferHeight = 480;

      //graphics.ApplyChanges();

      var initial_lives_n = 3;

      var loading_screen = new LoadingScreen(game);

      loading_screen.OnLoadEnd += () =>
      {
        loading_screen.start_fadeoff_transition = true;
      };

      loading_screen.OnLoadBegin += () =>
      {
        var t = new Thread(() =>
        {
          var sample_level = new TrashManLayer(game,
            new BaseLevelStats() { }, initial_lives_n, resume_state, game_mode);
          sample_level.OnLevelLost += (match_data) =>
          {
            StateManager.CleanupComponents(game);
            var tmp = Leaderboard.GetWakaModeStats();
            Leaderboard.SaveWakaModeStats(new WakaGarbageModeEntry()
              {
                  ShowAlwaysTutorial = tmp.ShowAlwaysTutorial,
                  GarbageDestroyed = 0,
                  LevelScore = 0,
                  Level = 0,
                  GreenTrashBinState = 0,
                  YellowTrashBinState = 0,
                  BlueTrashBinState = 0,
                  ManHoleState = 0,
                  EarthLife = 0,
                  TotalGameTime = tmp.TotalGameTime + sample_level.Actual_Total_Game_Time,
                  TimeToNextLevel = 0,
                  AudioState = AudioManager.Volume > 0,
              }
              );         
            game.Components.Add(new DefeatScreen(game, match_data));
          };

          var audio_manager = new AudioManager(game);
          var scene_renderer = new OverlaysLayer(game);
          var input_manager = new InputManager(game);

          sample_level.Enabled = false;
          input_manager.Enabled = false;
          scene_renderer.Enabled = false;

          game.Components.Add(sample_level);
          game.Components.Add(scene_renderer);
          game.Components.Add(audio_manager);

          var ui = new UILandscape(game);
          ui.OnQuitToMenu += () => sample_level.ForceLose();
          game.Components.Add(ui);
          game.Components.Add(input_manager);
          var r = new Random();
          game.Components.Add(new Background(game, BackgroundType.DefaulsBackground)); //(BackgroundType)r.Next(Background.NumberOf)));

          GC.Collect();
          GC.WaitForPendingFinalizers();

          LoadingScreen.LoadProccesComplete(game);
        });

        t.Start();
      };

      game.Components.Add(loading_screen);
    }

    #endregion

    public static bool first_transition = true;
    public static void CleanupComponents(Game game)
    {
      TransitionScreen transition = null;
      if (first_transition != true)
        transition = new TransitionScreen(game);
      for (int i = 0; i < game.Components.Count; i++)
      {
        if ((GameComponent)game.Components[i] is IPermanentComponent)
          continue;
        ((GameComponent)game.Components[i]).Dispose();
        i--;
      }
      //game.Components.Clear();
      if (first_transition != true)
      {
        game.Components.Add(transition);

        transition.OnTransitionStart += () =>
        {
          for (int i = 0; i < game.Components.Count; i++)
          {
            GameComponent gc = (GameComponent)game.Components[i];
            if (gc.GetType() != typeof(TransitionScreen) && gc.GetType() != typeof(LoadingScreen)) // 
              gc.Enabled = false;
          }
        };

        transition.OnTransitionEnd += () =>
        {
          var loadingScreenPresence = false;

          for (int i = 0; i < game.Components.Count; i++)
            if (game.Components[i].GetType() == typeof(LoadingScreen)) loadingScreenPresence = true;

          if (!loadingScreenPresence)
            for (int i = 0; i < game.Components.Count; i++)
            {
              GameComponent gc = (GameComponent)game.Components[i];
              if (gc != transition)
                gc.Enabled = true;
            }
        };
      }

      first_transition = false;
    }

  }
}
